﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using MusicStore.Silverlight.Helpers;
using MusicStore.Silverlight.MusicStoreService;
using MusicStore.Silverlight.Views;
using Album = MusicStore.Silverlight.MusicStoreService.Album;
using System.Linq;
using Castle.Core.Logging;
using MusicStore.Silverlight.Infrastructure;
using Structura.Silverlight.Infrastructure.ViewModel;

namespace MusicStore.Silverlight.ViewModels
{
	/// <summary>
	/// glues the model and the view, and offer facilities to manipulate/get the data
	/// </summary>
	public class AlbumViewModel : ViewModel, IAlbumViewModel
	{
		public AlbumViewModel()
		{
		}

		public ILogger Logger { get; set; }

		public new IAlbumView View { get { return (this as IViewModel).View as IAlbumView; } }

		public Album Album
		{
			get { return _album; }
			set
			{
				InnerSet(ref _album, value, "Album");
				
				PagedCollectionView tracks = new PagedCollectionView(_album.Tracks);
				// set a default sorter
				tracks.SortDescriptions.Add(new SortDescription("Number", ListSortDirection.Ascending));
				InnerSet(ref _tracks, tracks, "Tracks");
			}
		}
		private Album _album;
		
		public PagedCollectionView Tracks { get { return _tracks; } }
		private PagedCollectionView _tracks;

		public List<string> Genres
		{
			get { return _genres; }
			set { InnerSet(ref _genres, value, "Genres"); }
		}
		private List<string> _genres;

		/// <summary>
		/// get the data from the service or create a new album if 0 is passed in.
		/// the data will be assigned to the 
		/// Album property
		/// </summary>
		/// <param name="id"></param>
		public void GetAlbum(int id)
		{
			IsBusy = true;
			Init(() => InnerGetAlbum(id));
		}

		/// <summary>
		/// loads some data to be used in comboboxes
		/// after those are loaded it invokes the addictional operation function
		/// </summary>
		/// <param name="addictionaloperation">function/lambda that does addictional operations</param>
		private void Init(Action addictionaloperation)
		{
			Logger.Info("VM - Init Started");

			MusicStoreServiceClient client = ServiceHelper.GetServiceClient();
			client.GetGenresCompleted += (sender, e) =>
			{
				if (e.Error == null)
				{
					Genres = e.Result.Select(o => o.Name).ToList();
					Logger.Info("VM - Getting Genres Completed");

					addictionaloperation.Invoke();
				}
				else
				{
					IsBusy = false;
					Logger.Error("Error loading Genres", e.Error);
				}
			};
			Logger.Info("VM - Getting Genres");
			client.GetGenresAsync();
		}

		private void InnerGetAlbum(int id)
		{
			if (id == 0)
			{
				Logger.Info("VM - Creating New Album");
			
				Album = new Album();
				IsBusy = false;
			}
			else
			{
				// use the service to get a new album
				MusicStoreServiceClient client = ServiceHelper.GetServiceClient();
				client.GetAlbumCompleted += (sender, e) =>
														{
															if (e.Error == null)
															{
																Album = e.Result;

																Logger.InfoFormat("VM - Getting Album({0}) completed", id);
															}
															else
																Logger.ErrorFormat(e.Error, "Error loading Album({0})", id);
				
															IsBusy = false;
														};
				Logger.InfoFormat("VM - Getting Album({0})", id);
				client.GetAlbumAsync(id);
			}
		}

		public void DeleteAlbum()
		{
			IsBusy = true;
			int id = Album.Id;
			MusicStoreServiceClient client = ServiceHelper.GetServiceClient();
			client.DeleteCompleted += (sender, e) =>
												{
													if (e.Error == null)
													{
														View.AlbumDeleted();

														Logger.InfoFormat("VM - Album({0}) Deleted", id);
													}
													else
														Logger.ErrorFormat(e.Error, "Error Deleting Album({0})", id);
				
													IsBusy = false;
												};
			Logger.InfoFormat("VM - Deleting Album({0})", id);
				
			client.DeleteAsync(id);
		}

		public void SaveAlbum()
		{
			IsBusy = true;
			MusicStoreServiceClient client = ServiceHelper.GetServiceClient();
			client.SaveCompleted += (sender, e) =>
												{
													if (e.Error == null)
													{
														// update the album id for the newely created ones
														Album.Id = e.Result;
														View.AlbumSaved();
														Logger.Info("VM - Album Saved");
													}
													else
														Logger.Error("Error Saving Album", e.Error);
													IsBusy = false;
												};
			
			Logger.Info("VM - Saving Album");
			client.SaveAsync(Album);
		}

		public void AddTrack(int number, string title, string duration)
		{
			Logger.Info("VM - Adding Track");
			Album.Tracks.Add(new Track { Duration = duration, Number = number, Title = title });
		}

		public void RemoveTrack(Track track)
		{
			Logger.InfoFormat("VM - Removing Track({0})", track.Number);
			Album.Tracks.Remove(track);
		}

		public void UploadPreviewFile(System.IO.Stream filestream)
		{
			IsBusy = true;
			Logger.Info("VM - Uploading Preview");
			FileUploader.UploadFile(Album.Id, filestream, () =>
																			{
																				// reread the new Uri associated with the image
																				MusicStoreServiceClient client = ServiceHelper.GetServiceClient();
																				client.GetAlbumPreviewUriCompleted += (sender, e) =>
																																	{
																																		if (e.Error == null)
																																			Album.Image = e.Result;
																																		IsBusy = false;
																																	};
																				Logger.Info("VM - Retrieving Preview");
																				client.GetAlbumPreviewUriAsync(Album.Id);
																			});
		}

	}
}
